package com.example.springbootdemo.controller;

import com.example.springbootdemo.bean.response.ResponseInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceQuery;
import org.activiti.engine.task.Task;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author hh
 * @date 2022/3/21
 */
@Api(tags = "工作流引擎")
@RestController
@RequestMapping("test")
public class Activiti7Controller {

    private final RepositoryService repositoryService;

    private final RuntimeService runtimeService;

    private final TaskService taskService;

    public Activiti7Controller(RepositoryService repositoryService, RuntimeService runtimeService, TaskService taskService) {
        this.repositoryService = repositoryService;
        this.runtimeService = runtimeService;
        this.taskService = taskService;
    }

    @PostMapping("handleTask")
    @ApiOperation(value = "任务处理",notes = "任务负责人查询待办任务，选择任务进行处理，完成任务")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "processDefinitionKey",value = "流程key",dataType = "String",paramType = "query",example = ""),
            @ApiImplicitParam(name = "assignee",value = "任务负责人",dataType = "String",paramType = "query",example = ""),
    })
    public ResponseInfo handleTask(String processDefinitionKey, String assignee){
        List<Task> taskList = taskService.createTaskQuery()
                .processDefinitionKey(processDefinitionKey)
                .taskAssignee(assignee)
                .list();
        for (Task task : taskList) {
            String id = task.getId();
            // 完成任务
            taskService.complete(id);
            System.out.println("完成任务：" + task.getName());
        }
        return ResponseInfo.success();
    }


    @GetMapping("searchTask")
    @ApiOperation(value = "任务查询",notes = "流程启动后，各个任务的负责人就可以查询自己当前需要处理的任务，查询出来的任务都是该用户的待办任务")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "processDefinitionKey",value = "流程key",dataType = "String",paramType = "query",example = ""),
            @ApiImplicitParam(name = "assignee",value = "任务负责人",dataType = "String",paramType = "query",example = ""),
    })
    public ResponseInfo searchTask(String processDefinitionKey, String assignee){
        // 查询任务列表，根据流程定义的key和任务负责人
        List<Task> taskList = taskService.createTaskQuery()
                .processDefinitionKey(processDefinitionKey)
                .taskAssignee(assignee)
                .list();
        List<Map<String, Object>> resultList = new ArrayList<>();
        // 遍历任务列表
        for (Task task : taskList) {
            HashMap<String, Object> result = new HashMap<>();
            result.put("流程定义id", task.getProcessDefinitionId());
            result.put("流程实例id", task.getProcessInstanceId());
            result.put("任务负责人", task.getAssignee());
            result.put("任务id", task.getId());
            result.put("任务名称", task.getName());
            resultList.add(result);
        }
        return ResponseInfo.success(resultList);
    }



    @GetMapping("searchByKey")
    @ApiOperation(value = "根据流程key查询流程实例",notes = "查询流程实例")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "processDefinitionKey",value = "流程key",dataType = "String",paramType = "query",example = ""),
    })
    public ResponseInfo searchProcessInstance(String processDefinitionKey){
        ProcessInstanceQuery processInstanceQuery = runtimeService.createProcessInstanceQuery();
        List<ProcessInstance> processInstanceList = processInstanceQuery.processDefinitionKey(processDefinitionKey).list();

        int size = processInstanceList.size();
        if (size > 0){
            List<Map<String, String>> resultList = new ArrayList<>();
            for (ProcessInstance processInstance : processInstanceList) {
                Map<String, String> result = new HashMap<>();
                // 流程实例id
                result.put("processId", processInstance.getId());
                // 流程定义id
                result.put("processDefinitionKey", processInstance.getProcessDefinitionKey());
                resultList.add(result);
            }
            return ResponseInfo.success(resultList);
        }
        return ResponseInfo.fail();
    }



    @ApiOperation(value = "根据流程key启动流程", notes = "每一个流程有对应的一个key这个是某一个流程内固定的写在bpmn内的")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userKey", value = "启动流程的用户", dataType = "String", paramType = "query", example = ""),
            @ApiImplicitParam(name = "processKey", value = "流程key", dataType = "String", paramType = "query", example = "")
    })
    @PostMapping("start")
    public ResponseInfo start(String userKey, String processKey){
        Map<String, Object> variables = new HashMap<>();
        variables.put("userKey", userKey);
        ProcessInstance instance = runtimeService.startProcessInstanceByKey(processKey, variables);

        if (instance != null){
            HashMap<String, Object> result = new HashMap<>();
            // 流程实例id
            result.put("processId", instance.getId());
            // 流程定义id
            result.put("processDefinitionKey", instance.getProcessInstanceId());
            return ResponseInfo.success(result);
        }

        return ResponseInfo.fail();
    }

    @ApiOperation(value = "根据bpmnName部署流程", notes = "根据bpmnName部署流程")
    @ApiImplicitParam(name = "bpmnName", value = "设计的流程图名称", dataType = "String", paramType = "query", example = "myProcess")
    @PostMapping("deploy")
    public ResponseInfo deploy(String bpmnName){
        // 创建一个部署对象
        DeploymentBuilder deploymentBuilder = repositoryService.createDeployment().name("请假流程");
        Deployment deployment = deploymentBuilder.addClasspathResource("processes/" + bpmnName + ".bpmn")
                .deploy();

        if (deployment != null){
            Map<String, Object> result = new HashMap<>();
            result.put("deployId", deployment.getId());
            result.put("deployName", deployment.getName());
            return ResponseInfo.success(result);
        }

        return ResponseInfo.fail();
    }

    @ApiOperation(value = "根据部署ID删除流程",notes = "根据部署ID删除流程")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "deploymentId",value = "部署ID",dataType = "String",paramType = "query",example = "")
    })
    @PostMapping("delete")
    public ResponseInfo deleteProcess(String deploymentId){
        try {
            // 不带级联的删除：只能删除没有启动的流程，如果流程启动，就会抛出异常
            repositoryService.deleteDeployment(deploymentId);

            // 级联删除：不管流程是否启动，都能可以删除（emmm大概是一锅端）
            //repositoryService.deleteDeployment(deploymentId, true);
        } catch (Exception e){
            return ResponseInfo.fail();
        }

        return ResponseInfo.success();
    }

}
